package other.her.system.erp;

import com.alibaba.fastjson.JSONObject;
import com.rkhd.platform.sdk.api.annotations.RequestMethod;
import com.rkhd.platform.sdk.api.annotations.RestApi;
import com.rkhd.platform.sdk.api.annotations.RestMapping;
import com.rkhd.platform.sdk.api.annotations.RestQueryParam;
import com.rkhd.platform.sdk.data.model.SyncConfig__c;
import com.rkhd.platform.sdk.exception.ApiEntityServiceException;
import com.rkhd.platform.sdk.exception.AsyncTaskException;
import com.rkhd.platform.sdk.exception.XsyHttpException;
import com.rkhd.platform.sdk.log.Logger;
import com.rkhd.platform.sdk.log.LoggerFactory;
import com.rkhd.platform.sdk.service.FutureTaskService;
import com.rkhd.platform.sdk.service.XoqlService;
import org.apache.commons.lang.StringUtils;
import other.her.system.client.ErpUtils;
import other.her.system.utils.HCXObjectService;
import other.her.system.utils.ResultVo;

import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description 同步公共方法
 * @Author 黎炎松
 * 2024-10-11 10:10
 */
@RestApi(baseUrl = "/her/erpSync")
public class SyncSuper {
    private static final Logger LOGGER = LoggerFactory.getLogger();
    public static String FORMATTIME = "yyyy-MM-dd HH:mm:ss";
    public static String FORMAT = "yyyy-MM-dd";

    // 公司账套环境  惠尔瑞服务器地址：47.92.3.51  西子服务器地址：121.89.218.72
    public List<Map<String, String>> accountList = Arrays.asList(
        //new HashMap<String, String>(){{
        //    put("accountName", "测试账套");  // 账套名称
        //    put("accountVal", "4");                        // crm账套单选值
        //    put("domain", "http://47.92.3.51:8089/huierrui/kis");   // 请求路径
        //    put("speciaField", " ");   // 账套特殊字段(折后单价)
        //}}
        new HashMap<String, String>(){{
            put("accountName", "深圳市蕙尔瑞生物科技有限公司");  // 账套名称
            put("accountVal", "1");                        // crm账套单选值
            put("domain", "http://47.92.3.51:8089/huierrui/her");   // 请求路径
            put("speciaField", ",t0.FEntrySelfB0165 as discountPrice ");   // 账套特殊字段(折后单价)
        }},
        new HashMap<String, String>(){{
            put("accountName", "深圳市西子生物科技有限公司");
            put("accountVal", "2");
            put("domain", "http://121.89.218.72:8089/huierrui/szxz");
            put("speciaField", ",t0.FEntrySelfB0167 as discountPrice ");   // 账套特殊字段(折后单价)
        }},
        new HashMap<String, String>(){{
            put("accountName", "湖南精准医疗器械有限公司");
            put("accountVal", "3");
            put("domain", "http://121.89.218.72:8089/huierrui/hnjz");
            put("speciaField", " ");   // 账套特殊字段(折后单价)
        }}
    );

    // 同步的模块参数
    public static final Map<String, Map<String, String>> moduleMap = new HashMap<String, Map<String, String>>(){{
        put("cp", new HashMap<String, String>(){{ // 产品
            put("moduleKey", "cp"); // 模块标识
            put("moduleName", "产品"); // 同步的模块名称
            put("tableName", "t_ICItemCore"); // 表名
            put("idKey", "FItemID"); // id key
        }});
        put("xsck", new HashMap<String, String>(){{ // 销售出库
            put("moduleKey", "xsck");
            put("moduleName", "销售出库");
            put("tableName", "ICStockBill");
            put("idKey", "FInterID");
        }});
        put("qtck", new HashMap<String, String>(){{ // 其他出库
            put("moduleKey", "qtck");
            put("moduleName", "其他出库");
            put("tableName", "ICStockBill");
            put("idKey", "FInterID");
        }});
        put("xsfp", new HashMap<String, String>(){{ // 销售发票
            put("moduleKey", "xsfp");
            put("moduleName", "销售发票");
            put("tableName", "ICSale");
            put("idKey", "FInterID");
        }});
        put("skd", new HashMap<String, String>(){{ // 收款单
            put("moduleKey", "skd");
            put("moduleName", "收款单");
            put("tableName", "t_rp_NewReceiveBill");
            put("idKey", "FBillID");
        }});
    }};


    /**
     * 1.同步数据配置模块: 根据开始时间、结束时间手动同步数据 2.同步模块后续增量手动触发
     * @return
     */
    @RestMapping(value = "/syncErpData", method = RequestMethod.POST)
    public ResultVo syncErpData(@RestQueryParam(name = "configId") Long configId, @RestQueryParam(name = "syncKey") String syncKey) throws AsyncTaskException {
        LOGGER.info("同步配置模块手动触发数据同步开始");
        // 获取配置模块的信息判断同步的模块
        String syncType = "2";  // 同步的类型 1：根据时间范围初始化  2: 后续增量同步
        if (configId != null) {
            syncType = "1";
            SyncConfig__c syncConfig = new SyncConfig__c();
            syncConfig.setId(configId);
            syncConfig = HCXObjectService.get(syncConfig);
            syncKey = syncConfig.getSyncKey__c();
        }

        LOGGER.info("同步配置模块手动触发数据同步 syncKey = " + syncKey);
        switch (syncKey) {
            case "ERP_PRODUCT":
                // 产品
                FutureTaskService.instance().addFutureTask(SyncProduct.class, syncType);
                break;
            case "ERP_XXFP":
                // 销售发票
                FutureTaskService.instance().addFutureTask(SyncSaleInvoice.class, syncType);
                break;
            case "ERP_XXCK":
                // 销售出库
                FutureTaskService.instance().addFutureTask(SyncSaleOut.class, syncType);
                break;
            case "ERP_QTCK":
                // 其他出库
                FutureTaskService.instance().addFutureTask(SyncOtherOut.class, syncType);
                break;
            case "ERP_SKD":
                // 收款单
                FutureTaskService.instance().addFutureTask(SyncReceipt.class, syncType);
                break;
        }
        return ResultVo.success();
    }


    public static void main(String[] args) throws AsyncTaskException, ParseException {
        SyncSuper syncSuper = new SyncSuper();
        //syncSuper.longDateToString(1729475349000L, "YYYY-MM-DD HH:mm:ss");
    }


    /**
     * 根据标识获取系统配置
     * @param syncKey
     * @return
     */
    public SyncConfig__c getSyncConfig(String syncKey)  {
        String sql = String.format("select id,lastSyncTime__c,syncStartTime__c,syncEndTime__c from syncConfig__c where syncKey__c = '%s'", syncKey);
        SyncConfig__c syncConfig = HCXObjectService.queryOne(sql);

        if (syncConfig == null) {
            // 默认配置日期为当天
            syncConfig = new SyncConfig__c();
            String nowDate = longDateToString(System.currentTimeMillis(), FORMAT);
            syncConfig.setAttribute("startTime", nowDate);
            syncConfig.setAttribute("endTime", nowDate);
            return syncConfig;
        }

        // 处理日期
        Long syncStartTime = syncConfig.getSyncStartTime__c();
        Long syncEndTime = syncConfig.getSyncEndTime__c();
        if (syncStartTime != null && syncEndTime != null) {
            syncConfig.setAttribute("startTime", longDateToString(syncStartTime, FORMATTIME));
            syncConfig.setAttribute("endTime", longDateToString(syncEndTime, FORMATTIME));
        } else {
            String nowDate = longDateToString(System.currentTimeMillis(), FORMAT);
            syncConfig.setAttribute("startTime", nowDate);
            syncConfig.setAttribute("endTime", nowDate);
        }

        syncConfig.setLastSyncTime__c(longDateToString(System.currentTimeMillis(), FORMATTIME));
        LOGGER.info( " syncConfig = " + syncConfig);
        return syncConfig;
    }

    /**
     * 修改同步配置
     * @param syncConfig
     */
    public void upSyncConfig(SyncConfig__c syncConfig)  {
        if (syncConfig == null) {
            return;
        }

        // 更新同步配置 (只修改上次更新时间字段)
        SyncConfig__c upSyncConfig = new SyncConfig__c();
        upSyncConfig.setId(syncConfig.getId());
        upSyncConfig.setLastSyncTime__c(syncConfig.getLastSyncTime__c());
        HCXObjectService.update(upSyncConfig);
    }



    /**
     * 获取ERP有变化的数据
     * @param module 模块 cp：产品（物料）
     * @param account
     * @return
     * @throws XsyHttpException
     */
    public Map<String, String> getErpChangeData(Map<String, String> module, Map<String, String> account) {
        LOGGER.info("获取ERP当前模块有变化的数据：" + module.get("moduleName"));

        // 查询ERP当前模块有变化的数据
        String idKey = module.get("idKey");
        String erpSql = "select crm.id,crm.data_id,t.%s from crm_tableDataChange crm " +
                "left join %s t ON t.%s = crm.data_id where crm.module = '%s' ";
        // erpSql = "select crm.id,crm.data_id,t.FItemID from crm_tableDataChange crm left join t_ICItemCore t ON t.FItemID = crm.data_id where crm.module = 'cp'";
        erpSql = String.format(erpSql, idKey, module.get("tableName"), idKey, module.get("moduleKey"));

        List<JSONObject> erpChangeList = ErpUtils.query(erpSql, account.get("domain"));
        LOGGER.info("erpChangeList: " + erpChangeList.size());
        if (erpChangeList.size() <= 0) {
            return null;
        }

        // 判断新增、修改或者删除的id (关联的主表返回的主表id为null,则是已经删除)
        List<String> erpTableIds = new ArrayList<>();
        List<String> addUpIds = new ArrayList<>();
        List<String> delIds = new ArrayList<>();
        for (JSONObject tableData : erpChangeList) {
            erpTableIds.add(tableData.getString("id"));
            if (tableData.get(idKey) == null) {
                delIds.add(tableData.getString("data_id"));
            } else {
                addUpIds.add(tableData.getString("data_id"));
            }
        }

        // 返回数据
        Map<String, String> map = new HashMap<>();
        map.put("erpTableIds", StringUtils.join(erpTableIds, ","));
        map.put("addUpIds", StringUtils.join(addUpIds, ","));
        map.put("delIds", StringUtils.join(delIds, ","));
        LOGGER.info("idsMap: " + map);
        return map;
    }

    /**
     * 获取CRM数据map
     *
     * @param mapFlag
     * @param valKey 值的key
     * @param accountVal 所属账套
     * @param erpDataList erp数据
     * @return
     * @throws ApiEntityServiceException
     */
    public Map<String, Long> getCrmDataMap(String mapFlag, String valKey, int accountVal, List<JSONObject> erpDataList) throws ApiEntityServiceException {
        Map<String, Long> crmDataMap = new HashMap<>();

        String erpVals = erpDataList.stream().filter(v -> StringUtils.isNotBlank(v.getString(valKey))).map(v -> "'" + v.getString(valKey) + "'").distinct().collect(Collectors.joining(","));
        if (StringUtils.isBlank(erpVals)) {
            return crmDataMap;
        }

        String sql = "";
        String numberKey = "";
        switch (mapFlag) {
            case "user":
                // 用户 只匹配用户姓名
                sql = String.format("select id,name from user where name in (%s)", erpVals);
                numberKey = "name";
                break;
            case "account":
                // 客户
                sql = String.format("select id,ERPkeHu__c from account where zhangtao__c = %d and ERPkeHu__c in (%s)", accountVal, erpVals);
                numberKey = "ERPkeHu__c";
                break;
            case "product":
                // 产品
                sql = String.format("select id,productName from product where zhangtao__c = %d and productName in (%s)", accountVal, erpVals);
                numberKey = "productName";
                break;
            case "saleInvoice":
                // 销售发票
                sql = String.format("select id,name from IVSALESIC__c where zhangtao__c = %d and name in (%s)", accountVal, erpVals);
                numberKey = "name";
                break;
            case "saleOut":
                // 销售出库
                sql = String.format("select id,name from salesOutboundOrder__c where zhangtao__c = %d and name in (%s)", accountVal, erpVals);
                numberKey = "name";
                break;
        }

        String finalNumberKey = numberKey;
        crmDataMap = XoqlService.instance().query(sql).getRecords().stream().collect(Collectors.toMap(e -> e.getString(finalNumberKey), e1 -> e1.getLong("id"), (e, e1) -> e));
        LOGGER.info("crmDataMap: " + mapFlag + " ==> " + crmDataMap.size());

        return crmDataMap;
    }


    /**
     * 往ERP记录表新增数据
     * @param module
     * @param tableName
     * @param insertListIds
     */
    public void insertErpRecordData(String module, String tableName, List<JSONObject> insertListIds, String domain) {
        if (insertListIds.size() <= 0) {
            return;
        }

        String insertSql = "";
        LOGGER.info("新增 CRM table 表数据：" + insertListIds);
        for (JSONObject insertListId : insertListIds) {
            insertSql += String.format("INSERT INTO crm_tableDataChange (module, table_name, data_id, action, change_time)" +
                    " VALUES ('%s', '%s', %s, 'change', GETDATE());",module, tableName, insertListId.getString("id"));
        }

        ResultVo resultVo = ErpUtils.executeSql(insertSql, domain);
        LOGGER.info("新增 CRM table 表数据：" + resultVo.getCode());
    }


    /**
     * 删除CRM表中的数据
     * @param tableName
     * @param accountVal
     * @param delIds
     */
    public void delCrmTableData(String tableName, String accountVal, String delIds) {
        if (StringUtils.isBlank(delIds)) {
            return;
        }
        LOGGER.info("删除CRM table 表数据：" + delIds);

        String sql = String.format("select id from %s where zhangtao__c = %s and ERPID__c in (%s) ", tableName, accountVal, delIds);
        HCXObjectService.deleteBatch(HCXObjectService.queryAll(sql));
    }

    /**
     * 删除ERP记录表中的数据
     * @param erpTableIds
     * @param account
     */
    public void delErpRecordTable(String erpTableIds, Map<String, String> account) {
        if (StringUtils.isBlank(erpTableIds)) {
            return;
        }
        LOGGER.info("删除ERP table 记录表：" + erpTableIds);

        String erpSql = String.format("delete from crm_tableDataChange where id in (%s)", erpTableIds);
        ResultVo resultVo = ErpUtils.executeSql(erpSql, account.get("domain"));
        if (resultVo.getCode() != 200) {
            LOGGER.error("删除ERP table 记录表异常：" + resultVo.getMsg());
        }
    }


    /**
     * 获取时间戳
     * @param dateTimeString
     * @return
     */
    public Long getDateVal(String dateTimeString) {
        if (StringUtils.isBlank(dateTimeString)) {
            return null;
        }
        ZonedDateTime zonedDateTime = ZonedDateTime.parse(dateTimeString, DateTimeFormatter.ISO_OFFSET_DATE_TIME);
        // 转换为时间戳（毫秒）
        return zonedDateTime.toInstant().toEpochMilli();
    }

    /**
     * 日期转字符串
     * @param currentTime
     * @return
     * @throws ParseException
     */
    public String longDateToString(long currentTime, String format) {
        Date date = new Date(currentTime);
        return new SimpleDateFormat(format).format(date);
    }

    /**
     * 除
     * @param v1
     * @param v2
     * @return
     */
    public static double bgDivide(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.divide(b2).doubleValue();
    }

    /**
     * 加
     * @param v1
     * @param v2
     * @return
     */
    public static double bgAdd(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }

}
